fix buffer overflow on all emphasis flags set - #4498
Merged
Conversation
vitaut
requested changes
Jul 15, 2025
vitaut
left a comment
Contributor
There was a problem hiding this comment.
Thank you for the fix! Could you add a test case to color-test?
Contributor
Author
|
Yes, I hope to find time for it at the weekend. |
vitaut
approved these changes
Jul 20, 2025
Found while fuzzing some code.
The following code compiled with sanitizer overflows a buffer in
fmt::detail::ansi_color_escape.================================================================= ==1064648==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7b5f2a0004a0 at pc 0x56231c89794d bp 0x7fff64601a90 sp 0x7fff64601a80 WRITE of size 1 at 0x7b5f2a0004a0 thread T0 #0 0x56231c89794c in fmt::v11::detail::ansi_color_escape<char>::ansi_color_escape(fmt::v11::emphasis) (/home/dominic/tmp/fmt_overflow/a.out+0x2494c) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #1 0x56231c88fc0c in fmt::v11::detail::ansi_color_escape<char> fmt::v11::detail::make_emphasis<char>(fmt::v11::emphasis) (/home/dominic/tmp/fmt_overflow/a.out+0x1cc0c) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #2 0x56231c8b3b36 in decltype (({parm#2}.out)()) fmt::v11::formatter<fmt::v11::detail::styled_arg<char [5]>, char, void>::format<fmt::v11::context>(fmt::v11::detail::styled_arg<char [5]> const&, fmt::v11::context&) const (/home/dominic/tmp/fmt_overflow/a.out+0x40b36) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #3 0x56231c8a09ff in void fmt::v11::detail::value<fmt::v11::context>::format_custom<fmt::v11::detail::styled_arg<char [5]>, fmt::v11::formatter<fmt::v11::detail::styled_arg<char [5]>, char, void> >(void*, fmt::v11::parse_context<char>&, fmt::v11::context&) (/home/dominic/tmp/fmt_overflow/a.out+0x2d9ff) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #4 0x56231c895114 in fmt::v11::basic_format_arg<fmt::v11::context>::handle::format(fmt::v11::parse_context<char>&, fmt::v11::context&) const (/home/dominic/tmp/fmt_overflow/a.out+0x22114) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #5 0x56231c88f524 in fmt::v11::detail::default_arg_formatter<char>::operator()(fmt::v11::basic_format_arg<fmt::v11::context>::handle) (/home/dominic/tmp/fmt_overflow/a.out+0x1c524) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #6 0x56231c882ffb in fmt::v11::detail::vformat_to(fmt::v11::detail::buffer<char>&, fmt::v11::basic_string_view<char>, fmt::v11::basic_format_args<fmt::v11::context>, fmt::v11::detail::locale_ref) (/home/dominic/tmp/fmt_overflow/a.out+0xfffb) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #7 0x56231c883779 in fmt::v11::vprint(_IO_FILE*, fmt::v11::basic_string_view<char>, fmt::v11::basic_format_args<fmt::v11::context>) (/home/dominic/tmp/fmt_overflow/a.out+0x10779) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #8 0x56231c883905 in fmt::v11::vprint(fmt::v11::basic_string_view<char>, fmt::v11::basic_format_args<fmt::v11::context>) (/home/dominic/tmp/fmt_overflow/a.out+0x10905) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #9 0x56231c878cc9 in main (/home/dominic/tmp/fmt_overflow/a.out+0x5cc9) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) #10 0x7f5f2c0376b4 (/usr/lib/libc.so.6+0x276b4) (BuildId: 468e3585c794491a48ea75fceb9e4d6b1464fc35) #11 0x7f5f2c037768 in __libc_start_main (/usr/lib/libc.so.6+0x27768) (BuildId: 468e3585c794491a48ea75fceb9e4d6b1464fc35) #12 0x56231c878524 in _start (/home/dominic/tmp/fmt_overflow/a.out+0x5524) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) Address 0x7b5f2a0004a0 is located in stack of thread T0 at offset 160 in frame #0 0x56231c8b39d3 in decltype (({parm#2}.out)()) fmt::v11::formatter<fmt::v11::detail::styled_arg<char [5]>, char, void>::format<fmt::v11::context>(fmt::v11::detail::styled_arg<char [5]> const&, fmt::v11::context&) const (/home/dominic/tmp/fmt_overflow/a.out+0x409d3) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) This frame has 6 object(s): [32, 40) 'out' (line 589) [64, 80) '<unknown>' [96, 112) 'reset_color' (line 611) [128, 160) 'emphasis' (line 594) <== Memory access at offset 160 overflows this variable [192, 224) 'foreground' (line 599) [256, 288) 'background' (line 605) HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork (longjmp and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: stack-buffer-overflow (/home/dominic/tmp/fmt_overflow/a.out+0x2494c) (BuildId: 3cbd94becf314d362227e35ad13b65a34a8d0eec) in fmt::v11::detail::ansi_color_escape<char>::ansi_color_escape(fmt::v11::emphasis) Shadow bytes around the buggy address: 0x7b5f2a000200: f1 f1 f1 f1 f1 f1 01 f2 00 f2 f2 f2 00 f2 f2 f2 0x7b5f2a000280: 00 00 f2 f2 00 00 f2 f2 00 00 f2 f2 00 00 00 00 0x7b5f2a000300: f2 f2 f2 f2 00 00 00 00 00 00 00 f3 f3 f3 f3 f3 0x7b5f2a000380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7b5f2a000400: f1 f1 f1 f1 00 f2 f2 f2 00 00 f2 f2 00 00 f2 f2 =>0x7b5f2a000480: 00 00 00 00[f2]f2 f2 f2 00 00 00 00 f2 f2 f2 f2 0x7b5f2a000500: 00 00 00 00 f3 f3 f3 f3 00 00 00 00 00 00 00 00 0x7b5f2a000580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7b5f2a000600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7b5f2a000680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7b5f2a000700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==1064648==ABORTINGfmt version latest commit as of writing. git commit hash 553ec11